local a = true
local b = 1
local c = nil
local d = 2
local e = 0.005
local f = '3.1.0'
LuaPanda = {}
local g = LuaPanda
local h = {}
g.tools = h
g.curStackId = 0
local i
local j = {DISCONNECT_HOOK = 0, LITE_HOOK = 1, MID_HOOK = 2, ALL_HOOK = 3}
local k = {
    DISCONNECT = 0,
    WAIT_CMD = 1,
    STOP_ON_ENTRY = 2,
    RUN = 3,
    STEPOVER = 4,
    STEPIN = 5,
    STEPOUT = 6,
    STEPOVER_STOP = 7,
    STEPIN_STOP = 8,
    STEPOUT_STOP = 9,
    HIT_BREAKPOINT = 10
}
local l = '|*|'
local m = 3600 * 24
local n
local o
local p = {}
g.breaks = p
local q = ''
local r = ''
local s = ''
local t = ''
local u = ''
local v = {}
local w = {}
local x = false
local y = ''
local z
local A
local B
local C
local D
local E
local F
local G = 1
local H = 1
local I = {}
local J = ''
local K = true
local L = {}
local M = {}
local N = false
local O = false
local P = 'launch.json文件的配置项useCHook被设置为false.'
local Q = ''
local R = ''
local S = ''
local T = false
local U
local V
local W = false
local X = 0
local Y = 0
local Z = 3
local _ = 0
local a0
local a1
local a2 = 0
local a3
local a4 = 0
local a5 = {}
local a6 = false
if _VERSION == 'Lua 5.1' then
    a0 = loadstring
else
    a0 = load
end
local a7 =
    setmetatable(
    {},
    {__index = function(a8, a9)
            local aa = g.getWatchedVariable(a9, _G.LuaPanda.curStackId, false)
            return aa
        end, __newindex = function(a8, a9, ab)
            g.setVariableValue(a9, _G.LuaPanda.curStackId, ab)
        end}
)
function g.start(ac, ad)
    ac = tostring(ac or '127.0.0.1')
    ad = tonumber(ad) or 8818
    g.printToConsole('Debugger start. connect host:' .. ac .. ' port:' .. tostring(ad), 1)
    if B ~= nil then
        g.printToConsole('[Warning] 调试器已经启动，请不要再次调用start()', 1)
        return
    end
    g.changeRunState(k.DISCONNECT)
    if not g.reGetSock() then
        g.printToConsole('[Error] Start debugger but get Socket fail , please install luasocket!', 2)
        return
    end
    z = ac
    A = ad
    local ae = B and B:connect(z, A)
    if ae ~= nil then
        g.printToConsole('first connect success!')
        g.connectSuccess()
    else
        g.printToConsole('first connect failed!')
        g.changeHookState(j.DISCONNECT_HOOK)
    end
end
function g.connectSuccess()
    g.changeRunState(k.WAIT_CMD)
    g.printToConsole('connectSuccess', 1)
    local aa = g.debugger_wait_msg()
    if t == '' then
        local af = debug.getinfo(1, 'S')
        for ag, ah in pairs(af) do
            if ag == 'source' then
                t = ah
                g.printToVSCode('DebuggerFileName:' .. tostring(t))
                if E ~= nil then
                    E.sync_debugger_path(t)
                end
            end
        end
    end
    if u == '' then
        u = h.getFileSource()
        if E ~= nil then
            E.sync_tools_path(u)
        end
    end
    if aa == false then
        g.printToVSCode('[debugger error]初始化未完成, 建立连接但接收初始化消息失败。请更换端口重试', 2)
        return
    end
    g.printToVSCode('debugger init success', 1)
    g.changeHookState(j.ALL_HOOK)
    if E == nil then
        if a1 == nil and type(coroutine.create) == 'function' then
            g.printToConsole('change coroutine.create')
            a1 = coroutine.create
            coroutine.create = function(...)
                local ai = a1(...)
                table.insert(M, ai)
                g.changeCoroutineHookState()
                return ai
            end
        else
            g.printToConsole('restart coroutine')
            g.changeCoroutineHookState()
        end
    end
end
function g.clearData()
    C = nil
    D = nil
    p = {}
    a5 = {}
    g.breaks = p
    if E ~= nil then
        E.sync_breakpoints()
        E.clear_pathcache()
    end
end
function g.disconnect()
    g.printToConsole('Debugger disconnect', 1)
    g.clearData()
    g.changeHookState(j.DISCONNECT_HOOK)
    a2 = os.time()
    g.changeRunState(k.DISCONNECT)
    if B ~= nil then
        B:close()
    end
    if A == nil or z == nil then
        g.printToConsole(
            '[Warning] User call LuaPanda.disconnect() before set debug ip & port, please call LuaPanda.start() first!',
            2
        )
        return
    end
    g.reGetSock()
end
function g.getBreaks()
    return p
end
function g.getCWD()
    local aj = g.getSpecificFunctionStackLevel(v.func)
    if type(aj) ~= 'number' then
        aj = 2
    end
    local ak = v['source']
    if ak == nil and E ~= nil then
        ak = g.getPath(tostring(E.get_last_source()))
    end
    local af = debug.getinfo(aj, 'S')
    return 'cwd:      ' .. s .. '\ngetinfo:  ' .. af['source'] .. '\nformat:   ' .. tostring(ak)
end
function g.getBaseInfo()
    local al = {}
    local am = ''
    if jit and jit.version then
        am = ',' .. tostring(jit.version)
    end
    al[#al + 1] = 'Lua Ver:' .. _VERSION .. am .. ' | adapterVer:' .. tostring(F) .. ' | Debugger Ver:' .. tostring(f)
    local an = ''
    if E ~= nil then
        local ao, ap = E.sync_getLibVersion()
        local aq = ap ~= nil and tostring(ao) .. ' for ' .. tostring(math.ceil(ap)) or tostring(ao)
        al[#al + 1] = ' | hookLib Ver:' .. aq
        an = an .. '说明: 已加载 libpdebug 库.'
    else
        an = an .. '说明: 未能加载 libpdebug 库。原因请使用 LuaPanda.doctor() 查看'
    end
    local ar = false
    if type(_) == 'number' and _ == 1 then
        ar = true
    end
    al[#al + 1] = ' | supportREPL:' .. tostring(ar)
    al[#al + 1] = ' | useBase64EncodeString:' .. tostring(O)
    al[#al + 1] = ' | codeEnv:' .. tostring(C) .. '\n'
    al[#al + 1] = an
    if Q ~= nil and Q ~= '' then
        al[#al + 1] = '\n' .. Q
    end
    return table.concat(al)
end
function g.doctor()
    local al = {}
    if f ~= F then
        al[#al + 1] = '\n- 建议更新版本\nLuaPanda VSCode插件版本是' .. F .. ', LuaPanda.lua文件版本是' .. f .. '。建议检查并更新到最新版本。'
        al[#al + 1] = '\n更新方式   : https://github.com/Tencent/LuaPanda/blob/master/Docs/Manual/update.md'
        al[#al + 1] = '\nRelease版本: https://github.com/Tencent/LuaPanda/releases'
    end
    if E == nil then
        al[#al + 1] = '\n\n- libpdebug 库没有加载\n'
        if V then
            if a6 == true then
                al[#al + 1] = '用户使用 LuaPanda.lua 中 clibPath 变量指定了 plibdebug 的位置: ' .. D
                if g.tryRequireClib('libpdebug', D) then
                    al[#al + 1] = '\n引用成功'
                else
                    al[#al + 1] = '\n引用错误:' .. P
                end
            else
                local as, at
                if C == 'Darwin' then
                    as = '/?.so;'
                    at = 'mac'
                elseif C == 'Linux' then
                    as = '/?.so;'
                    at = 'linux'
                else
                    as = '/?.dll;'
                    at = 'win'
                end
                local au
                if _VERSION == 'Lua 5.1' then
                    au = '501'
                else
                    au = '503'
                end
                local av = D .. at .. '/x86/' .. au .. as
                local aw = D .. at .. '/x86_64/' .. au .. as
                al[#al + 1] = '尝试引用x64库: ' .. aw
                if g.tryRequireClib('libpdebug', aw) then
                    al[#al + 1] = '\n引用成功'
                else
                    al[#al + 1] = '\n引用错误:' .. P
                    al[#al + 1] = '\n尝试引用x86库: ' .. av
                    if g.tryRequireClib('libpdebug', av) then
                        al[#al + 1] = '\n引用成功'
                    else
                        al[#al + 1] = '\n引用错误:' .. P
                    end
                end
            end
        else
            al[#al + 1] = '原因是' .. P
        end
    end
    local ak = J
    if E ~= nil then
        ak = g.getPath(tostring(E.get_last_source()))
    end
    if not W and ak and ak ~= '' then
        local ax = g.fileExists(ak)
        if not ax then
            al[#al + 1] = '\n\n- 路径存在问题\n'
            local ay = g.stringSplit(ak, '/')
            local az = false
            for aA, a8 in pairs(g.getBreaks()) do
                if string.find(aA, ay[#ay], 1, true) then
                    az = true
                    al[#al + 1] = g.getCWD()
                    al[#al + 1] = '\nfilepath: ' .. aA
                    if T then
                        al[#al + 1] = '\n说明:从lua虚拟机获取到的是绝对路径，format使用getinfo路径。'
                    else
                        al[#al + 1] = '\n说明:从lua虚拟机获取到的是相对路径，调试器运行依赖的绝对路径(format)是来源于cwd+getinfo拼接。'
                    end
                    al[#al + 1] =
                        [[
                            filepath是VSCode通过获取到的文件正确路径 , 对比format和filepath，调整launch.json中CWD，或改变VSCode打开文件夹的位置。
                            使format和filepath一致即可。
                            如果format和filepath路径仅大小写不一致，设置launch.json中 pathCaseSensitivity:false 可忽略路径大小写";
                        ]]
                end
            end
            if az == false then
                al[#al + 1] =
                    '\n找不到文件:' .. ak .. ', 请检查路径是否正确。\n或者在VSCode文件' .. ay[#ay] .. '中打一个断点后，再执行一次doctor命令，查看路径分析结果。'
            end
        end
    end
    if G < 1 or d < 1 then
        al[#al + 1] = '\n\n- 日志等级\n'
        if G < 1 then
            al[#al + 1] = '当前日志等级是' .. G .. ', 会产生大量日志，降低调试速度。建议调整launch.json中logLevel:1'
        end
        if d < 1 then
            al[#al + 1] = '当前console日志等级是' .. d .. ', 过低的日志等级会降低调试速度，建议调整LuaPanda.lua文件头部consoleLogLevel=2'
        end
    end
    if #al == 0 then
        al[#al + 1] = '未检测出问题'
    end
    return table.concat(al)
end
function g.fileExists(aB)
    local aC = io.open(aB, 'r')
    if aC ~= nil then
        io.close(aC)
        return true
    else
        return false
    end
end
function g.getInfo()
    local al = {}
    al[#al + 1] = '\n- Base Info: \n'
    al[#al + 1] = g.getBaseInfo()
    al[#al + 1] = '\n\n- User Setting: \n'
    al[#al + 1] = 'stopOnEntry:' .. tostring(U) .. ' | '
    al[#al + 1] = 'logLevel:' .. G .. ' | '
    al[#al + 1] = 'consoleLogLevel:' .. d .. ' | '
    al[#al + 1] = 'pathCaseSensitivity:' .. tostring(K) .. ' | '
    al[#al + 1] = 'attachMode:' .. tostring(a) .. ' | '
    al[#al + 1] = 'autoPathMode:' .. tostring(W) .. ' | '
    if V then
        al[#al + 1] = 'useCHook:true'
    else
        al[#al + 1] = 'useCHook:false'
    end
    if G == 0 or d == 0 then
        al[#al + 1] = '\n说明:日志等级过低，会影响执行效率。请调整logLevel和consoleLogLevel值 >= 1'
    end
    al[#al + 1] = '\n\n- Path Info: \n'
    al[#al + 1] = 'clibPath: ' .. tostring(D) .. '\n'
    al[#al + 1] = 'debugger: ' .. g.getPath(t) .. '\n'
    al[#al + 1] = g.getCWD()
    if not W then
        if T then
            al[#al + 1] = '\n说明:从lua虚拟机获取到的是绝对路径，format使用getinfo路径。' .. S
        else
            al[#al + 1] =
                [[
                    说明:从lua虚拟机获取到的路径(getinfo)是相对路径，调试器运行依赖的绝对路径(format)是来源于cwd+getinfo拼接。
                    如format路径错误请尝试调整cwd或改变VSCode打开文件夹的位置。
                    也可以在format对应的文件下打一个断点，调整直到format和Breaks Info中断点路径完全一致。
                ]] ..
                S
        end
    else
        al[#al + 1] = '\n说明:已开启autoPathMode自动路径模式，调试器会根据getinfo获得的文件名自动查找文件位置，请确保VSCode打开的工程中不存在同名lua文件。'
    end
    if R ~= nil and R ~= '' then
        al[#al + 1] = '\n' .. R
    end
    al[#al + 1] = '\n\n- Breaks Info: \n'
    al[#al + 1] = g.serializeTable(g.getBreaks(), 'breaks')
    return table.concat(al)
end
function g.isInMain()
    return a3
end
function g.tryRequireClib(aD, aE)
    g.printToVSCode('tryRequireClib search : [' .. aD .. '] in ' .. aE)
    local aF = package.cpath
    package.cpath = package.cpath .. ';' .. aE
    g.printToVSCode('package.cpath:' .. package.cpath)
    local aG, aH =
        pcall(
        function()
            E = require(aD)
        end
    )
    if aG then
        if type(E) == 'table' and g.getTableMemberNum(E) > 0 then
            g.printToVSCode('tryRequireClib success : [' .. aD .. '] in ' .. aE)
            package.cpath = aF
            return true
        else
            P = 'tryRequireClib fail : require success, but member function num <= 0; [' .. aD .. '] in ' .. aE
            g.printToVSCode(P)
            E = nil
            package.cpath = aF
            return false
        end
    else
        P = aH
        g.printToVSCode('[Require clib error]: ' .. aH, 0)
    end
    package.cpath = aF
    return false
end
function g.revFindString(aI, aJ, aK)
    local aL = string.reverse(aI)
    local a8, aM = string.find(aL, aJ, 1, aK)
    if aM == nil then
        return nil
    end
    return string.len(aL) - aM + 1
end
function g.revSubString(aI, aN, aK)
    local aM = g.revFindString(aI, aN, aK)
    if aM == nil then
        return nil
    end
    return string.sub(aI, aM + 1, aI.length)
end
function g.stringSplit(aI, aO)
    local aP = {}
    string.gsub(
        aI,
        '[^' .. aO .. ']+',
        function(aQ)
            table.insert(aP, aQ)
        end
    )
    return aP
end
function g.setCallbackId(aR)
    if aR ~= nil and aR ~= '0' then
        q = tostring(aR)
    end
end
function g.getCallbackId()
    if q == nil then
        q = '0'
    end
    local aR = q
    q = '0'
    return aR
end
function g.trim(aS)
    return string.gsub(aS, '^%s*(.-)%s*$', '%1')
end
function g.getTableMemberNum(aT)
    local aU = 0
    if type(aT) ~= 'table' then
        g.printToVSCode('[debugger Error] getTableMemberNum get ' .. tostring(type(aT)), 2)
        return aU
    end
    for ag, ah in pairs(aT) do
        aU = aU + 1
    end
    return aU
end
function g.getMsgTable(aV, aW)
    aW = aW or 0
    local aX = {}
    aX['cmd'] = aV
    aX['callbackId'] = aW
    aX['info'] = {}
    return aX
end
function g.serializeTable(aY, aZ)
    local a_ = h.serializeTable(aY, aZ)
    return a_
end
function g.printToVSCode(aI, b0, type)
    type = type or 0
    b0 = b0 or 0
    if n == k.DISCONNECT or G > b0 then
        return
    end
    local b1 = {}
    b1['callbackId'] = '0'
    if type == 0 then
        b1['cmd'] = 'log'
    else
        b1['cmd'] = 'tip'
    end
    b1['info'] = {}
    b1['info']['logInfo'] = tostring(aI)
    g.sendMsg(b1)
end
function g.printToConsole(aI, b0)
    b0 = b0 or 0
    if d > b0 then
        return
    end
    print('[LuaPanda] ' .. tostring(aI))
end
function g.genUnifiedPath(aB)
    if aB == '' or aB == nil then
        return ''
    end
    if K == false then
        aB = string.lower(aB)
    end
    aB = string.gsub(aB, [[\]], '/')
    local b2 = g.stringSplit(aB, '/')
    local b3 = {}
    for ag, ah in ipairs(b2) do
        if ah == '.' then
        elseif ah == '..' and #b3 >= 1 and b3[#b3]:sub(2, 2) ~= ':' then
            table.remove(b3)
        else
            table.insert(b3, ah)
        end
    end
    local b4 = table.concat(b3, '/')
    if aB:sub(1, 1) == '/' then
        b4 = '/' .. b4
    end
    if 'Windows_NT' == C then
        if N then
            b4 = b4:gsub('^%a:', string.upper)
            S = '路径中Windows盘符已转为大写。'
        else
            b4 = b4:gsub('^%a:', string.lower)
            S = '路径中Windows盘符已转为小写。'
        end
    end
    return b4
end
function g.getCacheFormatPath(b5)
    if b5 == nil then
        return a5
    end
    return a5[b5]
end
function g.setCacheFormatPath(b5, b6)
    a5[b5] = b6
end
function g.sendLuaMemory()
    local b7 = collectgarbage('count')
    local b1 = {}
    b1['callbackId'] = '0'
    b1['cmd'] = 'refreshLuaMemory'
    b1['info'] = {}
    b1['info']['memInfo'] = tostring(b7)
    g.sendMsg(b1)
end
function g.reGetSock()
    if B ~= nil then
        pcall(
            function()
                B:close()
            end
        )
    end
    B = lua_extension and lua_extension.luasocket and lua_extension.luasocket().tcp()
    if B == nil then
        if
            pcall(
                function()
                    B = require('socket.core').tcp()
                end
            )
         then
            g.printToConsole('reGetSock success')
            B:settimeout(e)
        else
            if
                c and
                    pcall(
                        function()
                            B = c()
                        end
                    )
             then
                g.printToConsole('reGetSock custom success')
                B:settimeout(e)
            else
                g.printToConsole('[Error] reGetSock fail', 2)
                return false
            end
        end
    else
        g.printToConsole('reGetSock ue4 success')
        B:settimeout(e)
    end
    return true
end
function g.reConnect()
    if o == j.DISCONNECT_HOOK then
        if os.time() - a2 < b then
            g.printToConsole('Reconnect time less than 1s')
            g.printToConsole('os.time:' .. os.time() .. ' | stopConnectTime:' .. a2)
            return 1
        end
        if B == nil then
            g.reGetSock()
        end
        local ae, aG = B:connect(z, A)
        if ae == 1 or aG == 'already connected' then
            g.printToConsole('reconnect success')
            g.connectSuccess()
        else
            g.printToConsole('reconnect failed . retCode:' .. tostring(ae) .. '  status:' .. aG)
            a2 = os.time()
        end
        return 1
    end
    return 0
end
function g.sendMsg(b1)
    if O and b1['info'] ~= nil then
        for a8, ah in ipairs(b1['info']) do
            if ah['type'] == 'string' then
                ah['value'] = h.base64encode(ah['value'])
            end
        end
    end
    local b8 = i.encode(b1)
    if n == k.DISCONNECT then
        g.printToConsole('[debugger error] disconnect but want sendMsg:' .. b8, 2)
        g.disconnect()
        return
    end
    local b9, aH
    if
        pcall(
            function()
                b9, aH = B:send(b8 .. l .. '\n')
            end
        )
     then
        if b9 == nil then
            if aH == 'closed' then
                g.disconnect()
            end
        end
    end
end
function g.dataProcess(ba)
    g.printToVSCode('debugger get:' .. ba)
    local bb = i.decode(ba)
    if bb == nil then
        g.printToVSCode('[error] Json is error', 2)
        return
    end
    if bb.callbackId ~= '0' then
        g.setCallbackId(bb.callbackId)
    end
    if bb.cmd == 'continue' then
        g.changeRunState(k.RUN)
        local bc = g.getMsgTable('continue', g.getCallbackId())
        g.sendMsg(bc)
    elseif bb.cmd == 'stopOnStep' then
        g.changeRunState(k.STEPOVER)
        local bc = g.getMsgTable('stopOnStep', g.getCallbackId())
        g.sendMsg(bc)
        g.changeHookState(j.ALL_HOOK)
    elseif bb.cmd == 'stopOnStepIn' then
        g.changeRunState(k.STEPIN)
        local bc = g.getMsgTable('stopOnStepIn', g.getCallbackId())
        g.sendMsg(bc)
        g.changeHookState(j.ALL_HOOK)
    elseif bb.cmd == 'stopOnStepOut' then
        g.changeRunState(k.STEPOUT)
        local bc = g.getMsgTable('stopOnStepOut', g.getCallbackId())
        g.sendMsg(bc)
        g.changeHookState(j.ALL_HOOK)
    elseif bb.cmd == 'setBreakPoint' then
        g.printToVSCode('dataTable.cmd == setBreakPoint')
        local bd = bb.info.path
        bd = g.genUnifiedPath(bd)
        if W then
            bd = g.getFilenameFromPath(bd)
        end
        g.printToVSCode('setBreakPoint path:' .. tostring(bd))
        p[bd] = bb.info.bks
        for ag, ah in pairs(p) do
            if next(ah) == nil then
                p[ag] = nil
            end
        end
        if E ~= nil then
            E.sync_breakpoints()
        end
        if n ~= k.WAIT_CMD then
            if E == nil then
                local be, bf = g.checkHasBreakpoint(J)
                if be == false then
                    if bf == true then
                        g.changeHookState(j.MID_HOOK)
                    else
                        g.changeHookState(j.LITE_HOOK)
                    end
                else
                    g.changeHookState(j.ALL_HOOK)
                end
            end
        else
            local bc = g.getMsgTable('setBreakPoint', g.getCallbackId())
            g.sendMsg(bc)
            return
        end
        local bc = g.getMsgTable('setBreakPoint', g.getCallbackId())
        g.sendMsg(bc)
        g.printToVSCode('LuaPanda.getInfo()\n' .. g.getInfo())
        g.debugger_wait_msg()
    elseif bb.cmd == 'setVariable' then
        if
            n == k.STOP_ON_ENTRY or n == k.HIT_BREAKPOINT or n == k.STEPOVER_STOP or n == k.STEPIN_STOP or
                n == k.STEPOUT_STOP
         then
            local bc = g.getMsgTable('setVariable', g.getCallbackId())
            local bg = tonumber(bb.info.varRef)
            local ab = tostring(bb.info.newValue)
            local bh = true
            local a9 = tostring(bb.info.varName)
            local bi = string.sub(ab, 1, 1)
            local bj = string.sub(ab, -1, -1)
            if bi == bj then
                if bi == "'" or bi == '"' then
                    ab = string.sub(ab, 2, -2)
                    bh = false
                end
            end
            if ab == 'nil' and bh == true then
                ab = nil
                bh = false
            elseif ab == 'true' and bh == true then
                ab = true
                bh = false
            elseif ab == 'false' and bh == true then
                ab = false
                bh = false
            elseif tonumber(ab) and bh == true then
                ab = tonumber(ab)
                bh = false
            end
            if bb.info.stackId ~= nil and tonumber(bb.info.stackId) ~= nil and tonumber(bb.info.stackId) > 1 then
                g.curStackId = tonumber(bb.info.stackId)
            else
                g.printToVSCode('未能获取到堆栈层级，默认使用 this.curStackId;')
            end
            if bg < 10000 then
                bc.info = g.createSetValueRetTable(a9, ab, bh, g.curStackId, I[bg])
            else
                local bk
                if bg >= 10000 and bg < 20000 then
                    bk = 'local'
                elseif bg >= 20000 and bg < 30000 then
                    bk = 'global'
                elseif bg >= 30000 then
                    bk = 'upvalue'
                end
                bc.info = g.createSetValueRetTable(a9, ab, bh, g.curStackId, nil, bk)
            end
            g.sendMsg(bc)
            g.debugger_wait_msg()
        end
    elseif bb.cmd == 'getVariable' then
        if
            n == k.STOP_ON_ENTRY or n == k.HIT_BREAKPOINT or n == k.STEPOVER_STOP or n == k.STEPIN_STOP or
                n == k.STEPOUT_STOP
         then
            local bc = g.getMsgTable('getVariable', g.getCallbackId())
            local bg = tonumber(bb.info.varRef)
            if bg < 10000 then
                local bl = g.getVariableRef(bb.info.varRef, true)
                bc.info = bl
            elseif bg >= 10000 and bg < 20000 then
                if bb.info.stackId ~= nil and tonumber(bb.info.stackId) > 1 then
                    g.curStackId = tonumber(bb.info.stackId)
                    if type(w[g.curStackId - 1]) ~= 'table' or type(w[g.curStackId - 1].func) ~= 'function' then
                        local aI =
                            'getVariable getLocal currentCallStack ' ..
                            g.curStackId - 1 .. ' Error\n' .. g.serializeTable(w, 'currentCallStack')
                        g.printToVSCode(aI, 2)
                        bc.info = {}
                    else
                        local bm = g.getSpecificFunctionStackLevel(w[g.curStackId - 1].func)
                        local bl = g.getVariable(bm, true)
                        bc.info = bl
                    end
                end
            elseif bg >= 20000 and bg < 30000 then
                local bl = g.getGlobalVariable()
                bc.info = bl
            elseif bg >= 30000 then
                if bb.info.stackId ~= nil and tonumber(bb.info.stackId) > 1 then
                    g.curStackId = tonumber(bb.info.stackId)
                    if type(w[g.curStackId - 1]) ~= 'table' or type(w[g.curStackId - 1].func) ~= 'function' then
                        local aI =
                            'getVariable getUpvalue currentCallStack ' ..
                            g.curStackId - 1 .. ' Error\n' .. g.serializeTable(w, 'currentCallStack')
                        g.printToVSCode(aI, 2)
                        bc.info = {}
                    else
                        local bl = g.getUpValueVariable(w[g.curStackId - 1].func, true)
                        bc.info = bl
                    end
                end
            end
            g.sendMsg(bc)
            g.debugger_wait_msg()
        end
    elseif bb.cmd == 'initSuccess' then
        if bb.info.isNeedB64EncodeStr == 'true' then
            O = true
        else
            O = false
        end
        r = bb.info.luaFileExtension
        local bn = bb.info.TempFilePath
        if bn:sub(-1, -1) == [[\]] or bn:sub(-1, -1) == [[/]] then
            bn = bn:sub(1, -2)
        end
        y = bn
        s = g.genUnifiedPath(bb.info.cwd)
        G = tonumber(bb.info.logLevel) or 1
        if bb.info.autoPathMode == 'true' then
            W = true
        else
            W = false
        end
        if bb.info.pathCaseSensitivity == 'true' then
            K = true
        else
            K = false
        end
        if nil == C then
            if type(bb.info.OSType) == 'string' then
                C = bb.info.OSType
            else
                C = 'Windows_NT'
                Q = '未能检测出OSType, 可能是node os库未能加载，系统使用默认设置Windows_NT'
            end
        else
        end
        a6 = false
        if nil == D then
            if type(bb.info.clibPath) == 'string' then
                D = bb.info.clibPath
            else
                D = ''
                R = '未能正确获取libpdebug库所在位置, 可能无法加载libpdebug库。'
            end
        else
            a6 = true
        end
        if tostring(bb.info.useCHook) == 'true' then
            V = true
            if a6 == true then
                if luapanda_chook ~= nil then
                    E = luapanda_chook
                else
                    if not g.tryRequireClib('libpdebug', D) then
                        g.printToVSCode(
                            [[Require clib failed, use Lua to continue debug,
                            use LuaPanda.doctor() for more information.]],
                            1
                        )
                    end
                end
            else
                local as, at
                if C == 'Darwin' then
                    as = '/?.so;'
                    at = 'mac'
                elseif C == 'Linux' then
                    as = '/?.so;'
                    at = 'linux'
                else
                    as = '/?.dll;'
                    at = 'win'
                end
                local au
                if _VERSION == 'Lua 5.1' then
                    au = '501'
                else
                    au = '503'
                end
                local av = D .. at .. '/x86/' .. au .. as
                local aw = D .. at .. '/x86_64/' .. au .. as
                if luapanda_chook ~= nil then
                    E = luapanda_chook
                else
                    if not (g.tryRequireClib('libpdebug', aw) or g.tryRequireClib('libpdebug', av)) then
                        g.printToVSCode(
                            [[Require clib failed, use Lua to continue debug,
                            use LuaPanda.doctor() for more information.]],
                            1
                        )
                    end
                end
            end
        else
            V = false
        end
        F = tostring(bb.info.adapterVersion)
        local bc = g.getMsgTable('initSuccess', g.getCallbackId())
        local bo = 0
        if E ~= nil then
            bo = 1
            E.sync_config(G, K and 1 or 0)
            E.sync_tempfile_path(y)
            E.sync_cwd(s)
            E.sync_file_ext(r)
        end
        _ = 0
        if a0 ~= nil and type(a0) == 'function' then
            if pcall(a0('return 0')) then
                _ = 1
            end
        end
        local aY = {
            debuggerVer = tostring(f),
            UseHookLib = tostring(bo),
            UseLoadstring = tostring(_),
            isNeedB64EncodeStr = tostring(O)
        }
        bc.info = aY
        g.sendMsg(bc)
        U = bb.info.stopOnEntry
        if bb.info.stopOnEntry == 'true' then
            g.changeRunState(k.STOP_ON_ENTRY)
        else
            g.debugger_wait_msg(1)
            g.changeRunState(k.RUN)
        end
    elseif bb.cmd == 'getWatchedVariable' then
        local bc = g.getMsgTable('getWatchedVariable', g.getCallbackId())
        local bm = tonumber(bb.info.stackId)
        if _ == 1 then
            g.curStackId = bm
            local bp = g.processWatchedExp(bb.info)
            bc.info = bp
            g.sendMsg(bc)
            g.debugger_wait_msg()
            return
        else
            local bq = g.getWatchedVariable(bb.info.varName, bm, true)
            if bq ~= nil then
                bc.info = bq
            end
            g.sendMsg(bc)
            g.debugger_wait_msg()
        end
    elseif bb.cmd == 'stopRun' then
        local bc = g.getMsgTable('stopRun', g.getCallbackId())
        g.sendMsg(bc)
        g.disconnect()
    elseif 'LuaGarbageCollect' == bb.cmd then
        g.printToVSCode('collect garbage!')
        collectgarbage('collect')
        g.sendLuaMemory()
        g.debugger_wait_msg()
    elseif 'runREPLExpression' == bb.cmd then
        g.curStackId = tonumber(bb.info.stackId)
        local bp = g.processExp(bb.info)
        local bc = g.getMsgTable('runREPLExpression', g.getCallbackId())
        bc.info = bp
        g.sendMsg(bc)
        g.debugger_wait_msg()
    else
    end
end
function g.createSetValueRetTable(a9, ab, bh, br, bs, bk)
    local af
    local bt
    if bh == false then
        bt = {}
        bt[1] = {variablesReference = 0, value = ab, name = a9, type = type(ab)}
    else
        bt = g.getWatchedVariable(tostring(ab), br, true)
    end
    if bt ~= nil then
        local bu
        local bv = bt[1].value
        if bh == true then
            if tonumber(bt[1].variablesReference) > 0 then
                bu = I[tonumber(bt[1].variablesReference)]
            else
                if bt[1].type == 'number' then
                    bu = tonumber(bt[1].value)
                end
                if bt[1].type == 'string' then
                    bu = tostring(bt[1].value)
                    local bi = string.sub(bu, 1, 1)
                    local bj = string.sub(bu, -1, -1)
                    if bi == bj then
                        if bi == "'" or bi == '"' then
                            bu = string.sub(bu, 2, -2)
                            bv = bu
                        end
                    end
                end
                if bt[1].type == 'boolean' then
                    if bt[1].value == 'true' then
                        bu = true
                    else
                        bu = false
                    end
                end
                if bt[1].type == 'nil' then
                    bu = nil
                end
            end
        else
            bu = bt[1].value
        end
        local bw
        if type(bs) ~= table then
            bw = g.setVariableValue(a9, br, bu, bk)
        else
            bs[a9] = bu
            bw = true
        end
        if bt[1].type == 'string' then
            bv = '"' .. bv .. '"'
        end
        if bw ~= false and bw ~= nil then
            local bx = '变量 ' .. a9 .. ' 赋值成功'
            af = {
                success = 'true',
                name = bt[1].name,
                type = bt[1].type,
                value = bv,
                variablesReference = tostring(bt[1].variablesReference),
                tip = bx
            }
        else
            af = {success = 'false', type = type(bu), value = bv, tip = '找不到要设置的变量'}
        end
    else
        af = {success = 'false', type = nil, value = nil, tip = '输入的值无意义'}
    end
    return af
end
function g.receiveMessage(by)
    by = by or m
    B:settimeout(by)
    if #L > 0 then
        local bz = L[1]
        table.remove(L, 1)
        g.dataProcess(bz)
        return true
    end
    if n == k.DISCONNECT then
        g.disconnect()
        return false
    end
    if B == nil then
        g.printToConsole('[debugger error]接收信息失败  |  reason: socket == nil', 2)
        return
    end
    local bA, aH = B:receive()
    if bA == nil then
        if aH == 'closed' then
            g.printToConsole('[debugger error]接收信息失败  |  reason:' .. aH, 2)
            g.disconnect()
        end
        return false
    else
        local bB = string.sub(bA, 1, -1 * (l:len() + 1))
        local bC = string.find(bB, l, 1, true)
        if bC == nil then
            g.dataProcess(bB)
        else
            repeat
                local bD = string.sub(bB, 1, bC - 1)
                table.insert(L, bD)
                local bE = string.sub(bB, bC + l:len(), -1)
                bC = string.find(bE, l, 1, true)
            until not bC
            g.receiveMessage()
        end
        return true
    end
end
function g.debugger_wait_msg(by)
    by = by or m
    if n == k.WAIT_CMD then
        local aa = g.receiveMessage(by)
        return aa
    end
    if n == k.STEPOVER or n == k.STEPIN or n == k.STEPOUT or n == k.RUN then
        g.receiveMessage(0)
        return
    end
    if
        n == k.STEPOVER_STOP or n == k.STEPIN_STOP or n == k.STEPOUT_STOP or n == k.HIT_BREAKPOINT or
            n == k.STOP_ON_ENTRY
     then
        g.sendLuaMemory()
        g.receiveMessage(m)
        return
    end
end
function g.getStackTable(bF)
    local bG = 0
    if E ~= nil then
        bG = bF or Z
    else
        bG = bF or g.getSpecificFunctionStackLevel(v.func)
    end
    local bH = {}
    local bI = 0
    repeat
        local af = debug.getinfo(bG, 'SlLnf')
        if af == nil then
            break
        end
        if af.source == '=[C]' then
            break
        end
        local bJ = {}
        bJ.file = g.getPath(af)
        bJ.name = '文件名'
        bJ.line = tostring(af.currentline)
        local bK = bG - 3
        if E ~= nil then
            bK = bK + 2
        end
        bJ.index = tostring(bK)
        table.insert(bH, bJ)
        local bL = {}
        bL.name = bJ.file
        bL.line = bJ.line
        bL.func = af.func
        bL.realLy = bG
        table.insert(w, bL)
        if bI == 0 then
            bI = bG
        end
        bG = bG + 1
    until af == nil
    return bH, bI
end
function g.getPath(af)
    local bM = af
    if type(af) == 'table' then
        bM = af.source
    end
    local bN = g.getCacheFormatPath(bM)
    if bN ~= nil and type(bN) == 'string' then
        return bN
    end
    local bO = bM
    if r ~= '' then
        if string.find(r, '%%%d') then
            bM = string.gsub(bM, '%.[%w%.]+$', r)
        else
            bM = string.gsub(bM, '%.[%w%.]+$', '')
            bM = bM .. '.' .. r
        end
    end
    if bM:sub(1, 1) == '@' then
        bM = bM:sub(2)
    end
    if not W then
        if bM:sub(1, 1) == [[/]] or bM:sub(1, 2):match('^%a:') then
            T = true
        else
            T = false
            if s ~= '' then
                local bP = string.find(bM, s, 1, true)
                if bP == nil then
                    bM = s .. '/' .. bM
                end
            end
        end
    end
    bM = g.genUnifiedPath(bM)
    if W then
        bM = g.getFilenameFromPath(bM)
    end
    g.setCacheFormatPath(bO, bM)
    return bM
end
function g.getFilenameFromPath(aB)
    if aB == nil then
        return ''
    end
    return string.match(aB, '([^/]*)$')
end
function g.getCurrentFunctionStackLevel()
    local bQ = 2
    repeat
        local af = debug.getinfo(bQ, 'S')
        if af ~= nil then
            local bP = af.source == t or af.source == u
            if bP == false then
                return bQ - 1
            end
        end
        bQ = bQ + 1
    until not af
    return 0
end
function g.getSpecificFunctionStackLevel(bR)
    local bQ = 2
    repeat
        local af = debug.getinfo(bQ, 'f')
        if af ~= nil then
            if af.func == bR then
                return bQ - 1
            end
        end
        bQ = bQ + 1
    until not af
    return 0
end
function g.checkCurrentLayerisLua(bS)
    local af = debug.getinfo(bS, 'S')
    if af == nil then
        return nil
    end
    af.source = g.genUnifiedPath(af.source)
    if af ~= nil then
        for ag, ah in pairs(af) do
            if ag == 'what' then
                if ah == 'C' then
                    return false
                else
                    return true
                end
            end
        end
    end
    return nil
end
function g.isHitBreakpoint(af)
    local bT = tostring(af.currentline)
    local bU = af.source
    local bV = false
    if p[bU] then
        bV = true
    end
    if bV then
        for ag, ah in ipairs(p[bU]) do
            if tostring(ah['line']) == tostring(bT) then
                if ah['type'] == '0' then
                    local bW = g.IsMeetCondition(ah['condition'])
                    return bW
                elseif ah['type'] == '1' then
                    g.printToVSCode('[log point output]: ' .. ah['logMessage'], 1)
                else
                    return true
                end
            end
        end
    end
    return false
end
function g.IsMeetCondition(bX)
    w = {}
    I = {}
    H = 1
    g.getStackTable()
    g.curStackId = 2
    local bY = {['varName'] = bX}
    local bZ = g.processWatchedExp(bY)
    local b_ = false
    local function c0()
        if bZ[1]['isSuccess'] == 'true' then
            if bZ[1]['value'] == 'nil' or bZ[1]['value'] == 'false' and bZ[1]['type'] == 'boolean' then
                b_ = false
            else
                b_ = true
            end
        else
            b_ = false
        end
    end
    xpcall(
        c0,
        function()
            b_ = false
        end
    )
    return b_
end
function g.BP()
    g.printToConsole('BP()')
    if E == nil then
        if o == j.DISCONNECT_HOOK then
            g.printToConsole('BP() but NO HOOK')
            return
        end
        local ai, c1 = coroutine.running()
        if _VERSION == 'Lua 5.1' then
            if ai == nil then
                c1 = true
            else
                c1 = false
            end
        end
        if c1 == true then
            g.printToConsole('BP() in main')
        else
            g.printToConsole('BP() in coroutine')
            debug.sethook(ai, g.debug_hook, 'lrc')
        end
        x = true
    else
        if E.get_libhook_state() == j.DISCONNECT_HOOK then
            g.printToConsole('BP() but NO C HOOK')
            return
        end
        E.sync_bp_hit(1)
    end
    g.changeHookState(j.ALL_HOOK)
    return true
end
function g.checkHasBreakpoint(c2)
    local c3 = false
    if next(p) == nil then
        c3 = false
    else
        c3 = true
    end
    if c2 ~= nil then
        return p[c2] ~= nil, c3
    else
        return c3
    end
end
function g.checkfuncHasBreakpoint(c4, c5, c2)
    if p[c2] == nil then
        return false
    end
    c4 = tonumber(c4)
    c5 = tonumber(c5)
    if c4 >= c5 then
        return true
    end
    if #p[c2] <= 0 then
        return false
    else
        for ag, ah in ipairs(p[c2]) do
            if tonumber(ah.line) > c4 and tonumber(ah.line) <= c5 then
                return true
            end
        end
    end
    return false
end
function g.debug_hook(c6, c7)
    if g.reConnect() == 1 then
        return
    end
    if G == 0 then
        local c8 = {
            '-----enter debug_hook-----\n',
            'event:',
            c6,
            '  line:',
            tostring(c7),
            ' currentHookState:',
            o,
            ' currentRunState:',
            n
        }
        local c9 = table.concat(c8)
        g.printToVSCode(c9)
    end
    if o == j.LITE_HOOK then
        local ca = os.time()
        if ca - a4 > 1 then
            g.debugger_wait_msg(0)
            a4 = ca
        end
        return
    end
    local af
    local ai, c1 = coroutine.running()
    if _VERSION == 'Lua 5.1' then
        if ai == nil then
            c1 = true
        else
            c1 = false
        end
    end
    a3 = c1
    if c1 == true then
        af = debug.getinfo(2, 'Slf')
    else
        af = debug.getinfo(ai, 2, 'Slf')
    end
    af.event = c6
    g.real_hook_process(af)
end
function g.real_hook_process(af)
    local cb = false
    local c6 = af.event
    local bP = af.source == t or af.source == u
    if bP == true then
        return
    end
    if n == k.RUN or n == k.STEPOVER or n == k.STEPIN or n == k.STEPOUT then
        local ca = os.time()
        if ca - a4 > 1 then
            g.debugger_wait_msg(0)
            a4 = ca
        end
    end
    if af.source == '=[C]' then
        g.printToVSCode('current method is C')
        return
    end
    if af.source == 'temp buffer' then
        g.printToVSCode('current method is in temp buffer')
        return
    end
    if af.source == 'chunk' then
        g.printToVSCode('current method is in chunk')
        return
    end
    if af.short_src:match('%[string "') then
        if af.source:match('[\n;=]') then
            g.printToVSCode('hook jump Code String!')
            cb = true
        end
    end
    if cb == false then
        af.source = g.getPath(af)
    end
    if
        v['currentline'] == af['currentline'] and v['source'] == af['source'] and v['func'] == af['func'] and
            v['event'] == c6
     then
        g.printToVSCode('run twice')
    end
    if cb == false then
        v = af
        v['event'] = c6
        J = af.source
    end
    if G == 0 and cb == false then
        local c8 = {
            '[lua hook] event:',
            tostring(c6),
            ' currentRunState:',
            tostring(n),
            ' currentHookState:',
            tostring(o),
            ' jumpFlag:',
            tostring(cb)
        }
        for ag, ah in pairs(af) do
            table.insert(c8, tostring(ag))
            table.insert(c8, ':')
            table.insert(c8, tostring(ah))
            table.insert(c8, ' ')
        end
        local c9 = table.concat(c8)
        g.printToVSCode(c9)
    end
    local cc = false
    if tostring(c6) == 'line' and cb == false then
        if n == k.RUN or n == k.STEPOVER or n == k.STEPIN or n == k.STEPOUT then
            cc = g.isHitBreakpoint(af) or x
            if cc == true then
                g.printToVSCode(' + HitBreakpoint true')
                x = false
                X = 0
                Y = 0
                g.changeRunState(k.HIT_BREAKPOINT)
                g.SendMsgWithStack('stopOnBreakpoint')
            end
        end
    end
    if cc == true then
        return
    end
    if n == k.STEPOVER then
        if c6 == 'line' and X <= 0 and cb == false then
            X = 0
            g.changeRunState(k.STEPOVER_STOP)
            g.SendMsgWithStack('stopOnStep')
        elseif c6 == 'return' or c6 == 'tail return' then
            if X ~= 0 then
                X = X - 1
            end
        elseif c6 == 'call' then
            X = X + 1
        end
    elseif n == k.STOP_ON_ENTRY then
        if c6 == 'line' and cb == false then
            g.SendMsgWithStack('stopOnEntry')
        end
    elseif n == k.STEPIN then
        if c6 == 'line' and cb == false then
            g.changeRunState(k.STEPIN_STOP)
            g.SendMsgWithStack('stopOnStepIn')
        end
    elseif n == k.STEPOUT then
        if cb == false then
            if Y <= -1 then
                Y = 0
                g.changeRunState(k.STEPOUT_STOP)
                g.SendMsgWithStack('stopOnStepOut')
            end
        end
        if c6 == 'return' or c6 == 'tail return' then
            Y = Y - 1
        elseif c6 == 'call' then
            Y = Y + 1
        end
    end
    if E == nil then
        if n == k.RUN and cb == false and o ~= j.DISCONNECT_HOOK then
            local be, bf = g.checkHasBreakpoint(J)
            if be == false then
                if bf == true then
                    g.changeHookState(j.MID_HOOK)
                else
                    g.changeHookState(j.LITE_HOOK)
                end
            else
                local cd = g.checkfuncHasBreakpoint(v.linedefined, v.lastlinedefined, J)
                if cd then
                    g.changeHookState(j.ALL_HOOK)
                else
                    g.changeHookState(j.MID_HOOK)
                end
            end
            if (c6 == 'return' or c6 == 'tail return') and o == j.MID_HOOK then
                g.changeHookState(j.ALL_HOOK)
            end
        end
    end
end
function g.SendMsgWithStack(ce)
    local bc = g.getMsgTable(ce)
    local cf = 0
    bc['stack'], cf = g.getStackTable()
    if cf ~= 0 then
        v['func'] = debug.getinfo(cf - 1, 'f').func
    end
    g.sendMsg(bc)
    g.debugger_wait_msg()
end
function g.changeHookState(aS)
    if E == nil and o == aS then
        return
    end
    g.printToConsole('change hook state :' .. aS)
    if aS ~= j.DISCONNECT_HOOK then
        g.printToVSCode('change hook state : ' .. aS)
    end
    o = aS
    if aS == j.DISCONNECT_HOOK then
        if a == true then
            if E then
                E.lua_set_hookstate(j.DISCONNECT_HOOK)
            else
                debug.sethook(g.debug_hook, 'r', 1000000)
            end
        else
            if E then
                E.endHook()
            else
                debug.sethook()
            end
        end
    elseif aS == j.LITE_HOOK then
        if E then
            E.lua_set_hookstate(j.LITE_HOOK)
        else
            debug.sethook(g.debug_hook, 'r')
        end
    elseif aS == j.MID_HOOK then
        if E then
            E.lua_set_hookstate(j.MID_HOOK)
        else
            debug.sethook(g.debug_hook, 'rc')
        end
    elseif aS == j.ALL_HOOK then
        if E then
            E.lua_set_hookstate(j.ALL_HOOK)
        else
            debug.sethook(g.debug_hook, 'lrc')
        end
    end
    if E == nil then
        g.changeCoroutineHookState()
    end
end
function g.changeRunState(aS, cg)
    local ch
    if cg == 1 then
        ch = 'libc'
    else
        ch = 'lua'
    end
    g.printToConsole('changeRunState :' .. aS .. ' | from:' .. ch)
    if aS ~= k.DISCONNECT and aS ~= k.WAIT_CMD then
        g.printToVSCode('changeRunState :' .. aS .. ' | from:' .. ch)
    end
    if E ~= nil and cg ~= 1 then
        E.lua_set_runstate(aS)
    end
    n = aS
    w = {}
    I = {}
    H = 1
end
function g.changeCoroutineHookState(aS)
    aS = aS or o
    g.printToConsole('change [Coroutine] HookState: ' .. tostring(aS))
    for ag, ai in pairs(M) do
        if coroutine.status(ai) == 'dead' then
            table.remove(M, ag)
        else
            if aS == j.DISCONNECT_HOOK then
                if a == true then
                    debug.sethook(ai, g.debug_hook, 'r', 1000000)
                else
                    debug.sethook(ai, g.debug_hook, '')
                end
            elseif aS == j.LITE_HOOK then
                debug.sethook(ai, g.debug_hook, 'r')
            elseif aS == j.MID_HOOK then
                debug.sethook(ai, g.debug_hook, 'rc')
            elseif aS == j.ALL_HOOK then
                debug.sethook(ai, g.debug_hook, 'lrc')
            end
        end
    end
end
function g.clearEnv()
    if g.getTableMemberNum(a7) > 0 then
        a7 = setmetatable({}, getmetatable(a7))
    end
end
function g.showEnv()
    return a7
end
function g.findTableVar(ci, cj)
    if type(ci) ~= 'table' or type(cj) ~= 'table' then
        return nil
    end
    local ck = 2
    local cl = cj
    local cm = false
    repeat
        if ci[ck] ~= nil then
            local cn = nil
            xpcall(
                function()
                    cn = cl[tonumber(ci[ck])]
                end,
                function()
                    cn = nil
                end
            )
            if cn == nil then
                xpcall(
                    function()
                        cl = cl[tostring(ci[ck])]
                    end,
                    function()
                        cl = nil
                    end
                )
            else
                cl = cn
            end
            ck = ck + 1
            if cl == nil then
                return nil
            end
        else
            cm = true
        end
    until cm == true
    return cl
end
function g.createWatchedVariableInfo(co, cp)
    local cq = {}
    cq.name = co
    cq.type = tostring(type(cp))
    xpcall(
        function()
            cq.value = tostring(cp)
        end,
        function()
            cq.value = tostring(type(cp)) .. " [value can't trans to string]"
        end
    )
    cq.variablesReference = '0'
    if cq.type == 'table' or cq.type == 'function' or cq.type == 'userdata' then
        cq.variablesReference = H
        I[H] = cp
        H = H + 1
        if cq.type == 'table' then
            local cr = g.getTableMemberNum(cp)
            cq.value = cr .. ' Members ' .. cq.value
        end
    elseif cq.type == 'string' then
        cq.value = '"' .. cp .. '"'
    end
    return cq
end
function g.setGlobal(a9, ab)
    _G[a9] = ab
    g.printToVSCode('[setVariable success] 已设置  _G.' .. a9 .. ' = ' .. tostring(ab))
    return true
end
function g.setUpvalue(a9, ab, bm, ci)
    local aa = false
    local cs = g.getUpValueVariable(w[bm - 1].func, true)
    for ct, cj in ipairs(cs) do
        if cj.name == a9 then
            if #ci > 0 and type(cj) == 'table' then
                local cu = g.findTableVar(ci, I[cj.variablesReference])
                if cu ~= nil then
                    local bw = debug.setupvalue(w[bm - 1].func, ct, ab)
                    if bw == a9 then
                        g.printToConsole('[setVariable success1] 已设置 upvalue ' .. a9 .. ' = ' .. tostring(ab))
                        aa = true
                    else
                        g.printToConsole(
                            '[setVariable error1] 未能设置 upvalue ' ..
                                a9 .. ' = ' .. tostring(ab) .. ' , 返回结果: ' .. tostring(bw)
                        )
                    end
                    return aa
                end
            else
                local bw = debug.setupvalue(w[bm - 1].func, ct, ab)
                if bw == a9 then
                    g.printToConsole('[setVariable success] 已设置 upvalue ' .. a9 .. ' = ' .. tostring(ab))
                    aa = true
                else
                    g.printToConsole(
                        '[setVariable error] 未能设置 upvalue ' ..
                            a9 .. ' = ' .. tostring(ab) .. ' , 返回结果: ' .. tostring(bw)
                    )
                end
                return aa
            end
        end
    end
    return aa
end
function g.setLocal(a9, ab, ci, bm)
    local cv = tonumber(bm)
    local cw = cv and cv - 2 or 0
    local cx, aj = g.getVariable(nil, true, cw)
    local aa = false
    for ct, cj in ipairs(cx) do
        if cj.name == a9 then
            if #ci > 0 and type(cj) == 'table' then
                local cu = g.findTableVar(ci, I[cj.variablesReference])
                if cu ~= nil then
                    local bw = debug.setlocal(aj, cx[ct].index, ab)
                    if bw == a9 then
                        g.printToConsole('[setVariable success1] 已设置 local ' .. a9 .. ' = ' .. tostring(ab))
                        aa = true
                    else
                        g.printToConsole(
                            '[setVariable error1] 未能设置 local ' ..
                                a9 .. ' = ' .. tostring(ab) .. ' , 返回结果: ' .. tostring(bw)
                        )
                    end
                    return aa
                end
            else
                local bw = debug.setlocal(aj, cx[ct].index, ab)
                if bw == a9 then
                    g.printToConsole('[setVariable success] 已设置 local ' .. a9 .. ' = ' .. tostring(ab))
                    aa = true
                else
                    g.printToConsole(
                        '[setVariable error] 未能设置 local ' .. a9 .. ' = ' .. tostring(ab) .. ' , 返回结果: ' .. tostring(bw)
                    )
                end
                return aa
            end
        end
    end
    return aa
end
function g.setVariableValue(a9, bm, ab, cy)
    g.printToConsole(
        'setVariableValue | varName:' ..
            tostring(a9) .. ' stackId:' .. tostring(bm) .. ' newValue:' .. tostring(ab) .. ' limit:' .. tostring(cy)
    )
    if tostring(a9) == nil or tostring(a9) == '' then
        g.printToConsole('[setVariable Error] 被赋值的变量名为空', 2)
        g.printToVSCode('[setVariable Error] 被赋值的变量名为空', 2)
        return false
    end
    local ci = {}
    if a9:match('%.') then
        ci = g.stringSplit(a9, '%.')
        if type(ci) ~= 'table' or #ci < 1 then
            return false
        end
        a9 = ci[1]
    end
    if cy == 'local' then
        local aa = g.setLocal(a9, ab, ci, bm)
        return aa
    elseif cy == 'upvalue' then
        local aa = g.setUpvalue(a9, ab, bm, ci)
        return aa
    elseif cy == 'global' then
        local aa = g.setGlobal(a9, ab)
        return aa
    else
        local aa = g.setLocal(a9, ab, ci, bm) or g.setUpvalue(a9, ab, bm, ci) or g.setGlobal(a9, ab)
        g.printToConsole('set Value res :' .. tostring(aa))
        return aa
    end
end
function g.getWatchedVariable(a9, bm, cz)
    g.printToConsole(
        'getWatchedVariable | varName:' ..
            tostring(a9) .. ' stackId:' .. tostring(bm) .. ' isFormatVariable:' .. tostring(cz)
    )
    if tostring(a9) == nil or tostring(a9) == '' then
        return nil
    end
    if type(w[bm - 1]) ~= 'table' or type(w[bm - 1].func) ~= 'function' then
        local aI =
            'getWatchedVariable currentCallStack ' .. bm - 1 .. ' Error\n' .. g.serializeTable(w, 'currentCallStack')
        g.printToVSCode(aI, 2)
        return nil
    end
    local cA = a9
    local ci = {}
    if a9:match('%.') then
        ci = g.stringSplit(a9, '%.')
        if type(ci) ~= 'table' or #ci < 1 then
            return nil
        end
        a9 = ci[1]
    end
    local cB = {}
    local aj = g.getSpecificFunctionStackLevel(w[bm - 1].func)
    local cx = g.getVariable(aj, cz)
    local cs = g.getUpValueVariable(w[bm - 1].func, cz)
    local cC = {}
    table.insert(cC, cx)
    table.insert(cC, cs)
    for a8, cx in ipairs(cC) do
        for ct, cj in ipairs(cx) do
            if cj.name == a9 then
                if #ci > 0 and type(cj) == 'table' then
                    local cu = g.findTableVar(ci, I[cj.variablesReference])
                    if cu ~= nil then
                        if cz then
                            local cq = g.createWatchedVariableInfo(cA, cu)
                            table.insert(cB, cq)
                            return cB
                        else
                            return cu.value
                        end
                    end
                else
                    if cz then
                        table.insert(cB, cj)
                        return cB
                    else
                        return cj.value
                    end
                end
            end
        end
    end
    if _G[a9] ~= nil then
        if #ci > 0 and type(_G[a9]) == 'table' then
            local cu = g.findTableVar(ci, _G[a9])
            if cu ~= nil then
                if cz then
                    local cq = g.createWatchedVariableInfo(cA, cu)
                    table.insert(cB, cq)
                    return cB
                else
                    return cu
                end
            end
        else
            if cz then
                local cq = g.createWatchedVariableInfo(a9, _G[a9])
                table.insert(cB, cq)
                return cB
            else
                return _G[a9]
            end
        end
    end
    g.printToConsole('getWatchedVariable not find variable')
    return nil
end
function g.getVariableRef(cD)
    local cE = tonumber(cD)
    local cB = {}
    if tostring(type(I[cE])) == 'table' then
        for cF, ah in pairs(I[cE]) do
            local cq = {}
            if type(cF) == 'string' then
                cq.name = '"' .. tostring(cF) .. '"'
            else
                cq.name = tostring(cF)
            end
            cq.type = tostring(type(ah))
            xpcall(
                function()
                    cq.value = tostring(ah)
                end,
                function()
                    cq.value = tostring(type(ah)) .. " [value can't trans to string]"
                end
            )
            cq.variablesReference = '0'
            if cq.type == 'table' or cq.type == 'function' or cq.type == 'userdata' then
                cq.variablesReference = H
                I[H] = ah
                H = H + 1
                if cq.type == 'table' then
                    local cr = g.getTableMemberNum(ah)
                    cq.value = cr .. ' Members ' .. (cq.value or '')
                end
            elseif cq.type == 'string' then
                cq.value = '"' .. ah .. '"'
            end
            table.insert(cB, cq)
        end
        local cG = getmetatable(I[cE])
        if cG ~= nil and type(cG) == 'table' then
            local cq = {}
            cq.name = '_Metatable_'
            cq.type = tostring(type(cG))
            xpcall(
                function()
                    cq.value = '元表 ' .. tostring(cG)
                end,
                function()
                    cq.value = "元表 [value can't trans to string]"
                end
            )
            cq.variablesReference = H
            I[H] = cG
            H = H + 1
            table.insert(cB, cq)
        end
    elseif tostring(type(I[cE])) == 'function' then
        cB = g.getUpValueVariable(I[cE], true)
    elseif tostring(type(I[cE])) == 'userdata' then
        local cH = getmetatable(I[cE])
        if cH ~= nil and type(cH) == 'table' then
            local cq = {}
            cq.name = '_Metatable_'
            cq.type = tostring(type(cH))
            xpcall(
                function()
                    cq.value = '元表 ' .. tostring(cH)
                end,
                function()
                    cq.value = "元表 [value can't trans to string]"
                end
            )
            cq.variablesReference = H
            I[H] = cH
            H = H + 1
            table.insert(cB, cq)
            if cH.__pairs ~= nil and type(cH.__pairs) == 'function' then
                for cF, ah in pairs(I[cE]) do
                    local cq = {}
                    cq.name = tostring(cF)
                    cq.type = tostring(type(ah))
                    xpcall(
                        function()
                            cq.value = tostring(ah)
                        end,
                        function()
                            cq.value = tostring(type(ah)) .. " [value can't trans to string]"
                        end
                    )
                    cq.variablesReference = '0'
                    if cq.type == 'table' or cq.type == 'function' or cq.type == 'userdata' then
                        cq.variablesReference = H
                        I[H] = ah
                        H = H + 1
                        if cq.type == 'table' then
                            local cr = g.getTableMemberNum(ah)
                            cq.value = cr .. ' Members ' .. (cq.value or '')
                        end
                    elseif cq.type == 'string' then
                        cq.value = '"' .. ah .. '"'
                    end
                    table.insert(cB, cq)
                end
            end
        end
    end
    return cB
end
function g.getGlobalVariable(...)
    local cB = {}
    for ag, ah in pairs(_G) do
        local cq = {}
        cq.name = tostring(ag)
        cq.type = tostring(type(ah))
        xpcall(
            function()
                cq.value = tostring(ah)
            end,
            function()
                cq.value = tostring(type(ah)) .. " [value can't trans to string]"
            end
        )
        cq.variablesReference = '0'
        if cq.type == 'table' or cq.type == 'function' or cq.type == 'userdata' then
            cq.variablesReference = H
            I[H] = ah
            H = H + 1
            if cq.type == 'table' then
                local cr = g.getTableMemberNum(ah)
                cq.value = cr .. ' Members ' .. (cq.value or '')
            end
        elseif cq.type == 'string' then
            cq.value = '"' .. ah .. '"'
        end
        table.insert(cB, cq)
    end
    return cB
end
function g.getUpValueVariable(cI, cz)
    local cJ = true
    if cz == true then
        cJ = false
    end
    cI = cI or v.func
    local cB = {}
    if cI == nil then
        return cB
    end
    local ct = 1
    repeat
        local cF, ah = debug.getupvalue(cI, ct)
        if cF then
            local cq = {}
            cq.name = cF
            cq.type = tostring(type(ah))
            cq.variablesReference = '0'
            if cJ == false then
                xpcall(
                    function()
                        cq.value = tostring(ah)
                    end,
                    function()
                        cq.value = tostring(type(ah)) .. " [value can't trans to string]"
                    end
                )
                if cq.type == 'table' or cq.type == 'function' or cq.type == 'userdata' then
                    cq.variablesReference = H
                    I[H] = ah
                    H = H + 1
                    if cq.type == 'table' then
                        local cr = g.getTableMemberNum(ah)
                        cq.value = cr .. ' Members ' .. (cq.value or '')
                    end
                elseif cq.type == 'string' then
                    cq.value = '"' .. ah .. '"'
                end
            else
                cq.value = ah
            end
            table.insert(cB, cq)
            ct = ct + 1
        end
    until not cF
    return cB
end
function g.getVariable(bS, cz, cw)
    local cJ = true
    if cz == true then
        cJ = false
    end
    local aj = 0
    if bS ~= nil and type(bS) == 'number' then
        aj = bS + 1
    else
        aj = g.getSpecificFunctionStackLevel(v.func)
    end
    if aj == 0 then
        g.printToVSCode('[error]获取层次失败！', 2)
        return
    end
    local cB = {}
    local cK = aj
    local ag = 1
    if type(cw) == 'number' then
        cK = cK + cw
    end
    repeat
        local cF, ah = debug.getlocal(cK, ag)
        if cF == nil then
            break
        end
        if '(*temporary)' ~= tostring(cF) then
            local cq = {}
            cq.name = cF
            cq.type = tostring(type(ah))
            cq.variablesReference = '0'
            cq.index = ag
            if cJ == false then
                xpcall(
                    function()
                        cq.value = tostring(ah)
                    end,
                    function()
                        cq.value = tostring(type(ah)) .. " [value can't trans to string]"
                    end
                )
                if cq.type == 'table' or cq.type == 'function' or cq.type == 'userdata' then
                    cq.variablesReference = H
                    I[H] = ah
                    H = H + 1
                    if cq.type == 'table' then
                        local cr = g.getTableMemberNum(ah)
                        cq.value = cr .. ' Members ' .. (cq.value or '')
                    end
                elseif cq.type == 'string' then
                    cq.value = '"' .. ah .. '"'
                end
            else
                cq.value = ah
            end
            local cL = g.checkSameNameVar(cB, cq)
            if cL ~= 0 then
                cB[cL] = cq
            else
                table.insert(cB, cq)
            end
        end
        ag = ag + 1
    until cF == nil
    return cB, cK - 1
end
function g.checkSameNameVar(cB, cq)
    for ag, ah in pairs(cB) do
        if ah.name == cq.name then
            return ag
        end
    end
    return 0
end
function g.processExp(aX)
    local cM
    local cq = {}
    cq.isSuccess = 'true'
    if aX ~= nil then
        local cN = g.trim(tostring(aX.Expression))
        local cO = false
        if cO == false then
            if cN:find('p ', 1, true) == 1 then
                cN = cN:sub(3)
            end
            local cP = 'return ' .. cN
            local aC = a0(cP) or a0(cN)
            if type(aC) == 'function' then
                if _VERSION == 'Lua 5.1' then
                    setfenv(aC, a7)
                else
                    debug.setupvalue(aC, 1, a7)
                end
                xpcall(
                    function()
                        cM = aC()
                    end,
                    function()
                        cM = '输入错误指令。\n + 请检查指令是否正确\n + 指令仅能在[暂停在断点时]输入, 请不要在程序持续运行时输入'
                        cq.isSuccess = false
                    end
                )
            else
                cM = '指令执行错误。\n + 请检查指令是否正确\n + 可以直接输入表达式，执行函数或变量名，并观察执行结果'
                cq.isSuccess = false
            end
        end
    end
    cq.name = 'Exp'
    cq.type = tostring(type(cM))
    xpcall(
        function()
            cq.value = tostring(cM)
        end,
        function(cQ)
            cq.value = tostring(type(cM)) .. " [value can't trans to string] " .. cQ
            cq.isSuccess = false
        end
    )
    cq.variablesReference = '0'
    if cq.type == 'table' or cq.type == 'function' or cq.type == 'userdata' then
        I[H] = cM
        cq.variablesReference = H
        H = H + 1
        if cq.type == 'table' then
            local cr = g.getTableMemberNum(cM)
            cq.value = cr .. ' Members ' .. cq.value
        end
    elseif cq.type == 'string' then
        cq.value = '"' .. cM .. '"'
    end
    g.clearEnv()
    local cR = {}
    table.insert(cR, cq)
    return cR
end
function g.processWatchedExp(aX)
    local cM
    local cN = 'return ' .. tostring(aX.varName)
    g.printToConsole('processWatchedExp | expression: ' .. cN)
    local aC = a0(cN)
    local cq = {}
    cq.isSuccess = 'true'
    if type(aC) == 'function' then
        if _VERSION == 'Lua 5.1' then
            setfenv(aC, a7)
        else
            debug.setupvalue(aC, 1, a7)
        end
        xpcall(
            function()
                cM = aC()
            end,
            function()
                cM = '输入了错误的变量信息'
                cq.isSuccess = 'false'
            end
        )
    else
        cM = '未能找到变量的值'
        cq.isSuccess = 'false'
    end
    cq.name = aX.varName
    cq.type = tostring(type(cM))
    xpcall(
        function()
            cq.value = tostring(cM)
        end,
        function()
            cq.value = tostring(type(cM)) .. " [value can't trans to string]"
            cq.isSuccess = 'false'
        end
    )
    cq.variablesReference = '0'
    if cq.type == 'table' or cq.type == 'function' or cq.type == 'userdata' then
        I[H] = cM
        cq.variablesReference = H
        H = H + 1
        if cq.type == 'table' then
            local cr = g.getTableMemberNum(cM)
            cq.value = cr .. ' Members ' .. cq.value
        end
    elseif cq.type == 'string' then
        cq.value = '"' .. cM .. '"'
    end
    local cR = {}
    table.insert(cR, cq)
    return cR
end
function h.getFileSource()
    local af = debug.getinfo(1, 'S')
    for ag, ah in pairs(af) do
        if ag == 'source' then
            return ah
        end
    end
end
function h.printTable(aT, aZ, cS)
    local aI = h.show(aT, aZ, cS)
    print(aI)
end
function h.serializeTable(aT, aZ, cS)
    local aI = h.show(aT, aZ, cS)
    return aI
end
function h.show(aT, aZ, cS)
    local cT
    local cU
    local function cV(aT)
        return next(aT) == nil
    end
    local function cW(cX)
        local cY = tostring(cX)
        if type(cX) == 'function' then
            local af = debug.getinfo(cX, 'S')
            if af.what == 'C' then
                return string.format('%q', cY .. ', C function')
            else
                return string.format(
                    '%q',
                    cY .. ', defined in (' .. af.linedefined .. '-' .. af.lastlinedefined .. ')' .. af.source
                )
            end
        elseif type(cX) == 'number' or type(cX) == 'boolean' then
            return cY
        else
            return string.format('%q', cY)
        end
    end
    local function cZ(c_, aZ, cS, d0, d1)
        cS = cS or ''
        d0 = d0 or {}
        d1 = d1 or aZ
        cT = cT .. cS .. d1
        if type(c_) ~= 'table' then
            cT = cT .. ' = ' .. cW(c_) .. ';\n'
        else
            if d0[c_] then
                cT = cT .. ' = {}; -- ' .. d0[c_] .. ' (self reference)\n'
                cU = cU .. aZ .. ' = ' .. d0[c_] .. ';\n'
            else
                d0[c_] = aZ
                if cV(c_) then
                    cT = cT .. ' = {};\n'
                else
                    cT = cT .. ' = {\n'
                    for ag, ah in pairs(c_) do
                        ag = cW(ag)
                        local d2 = string.format('%s[%s]', aZ, ag)
                        d1 = string.format('[%s]', ag)
                        cZ(ah, d2, cS .. '   ', d0, d1)
                    end
                    cT = cT .. cS .. '};\n'
                end
            end
        end
    end
    aZ = aZ or 'PRINT_Table'
    if type(aT) ~= 'table' then
        return aZ .. ' = ' .. cW(aT)
    end
    cT, cU = '', ''
    cZ(aT, aZ, cS)
    return cT .. cU
end
function h.createJson()
    local math = require('math')
    local string = require('string')
    local table = require('table')
    local i = {}
    local d3 = {}
    i.EMPTY_ARRAY = {}
    i.EMPTY_OBJECT = {}
    local d4
    local d5
    local d6
    local d7
    local d8
    local d9
    local da
    local db
    local dc
    local dd
    function i.encode(ah)
        if ah == nil then
            return 'null'
        end
        local de = type(ah)
        if de == 'string' then
            return '"' .. d3.encodeString(ah) .. '"'
        end
        if de == 'number' or de == 'boolean' then
            return tostring(ah)
        end
        if de == 'table' then
            local df = {}
            local dg, dh = dc(ah)
            if dg then
                for ct = 1, dh do
                    table.insert(df, i.encode(ah[ct]))
                end
            else
                for ct, di in pairs(ah) do
                    if dd(ct) and dd(di) then
                        table.insert(df, '"' .. d3.encodeString(ct) .. '":' .. i.encode(di))
                    end
                end
            end
            if dg then
                return '[' .. table.concat(df, ',') .. ']'
            else
                return '{' .. table.concat(df, ',') .. '}'
            end
        end
        if de == 'function' and ah == i.null then
            return 'null'
        end
        assert(false, 'encode attempt to encode unsupported type ' .. de .. ':' .. tostring(ah))
    end
    function i.decode(aS, dj)
        dj = dj and dj or 1
        dj = da(aS, dj)
        assert(dj <= string.len(aS), 'Unterminated JSON encoded object found at position in [' .. aS .. ']')
        local dk = string.sub(aS, dj, dj)
        if dk == '{' then
            return d8(aS, dj)
        end
        if dk == '[' then
            return d4(aS, dj)
        end
        if string.find('+-0123456789.e', dk, 1, true) then
            return d7(aS, dj)
        end
        if dk == [["]] or dk == [[']] then
            return d9(aS, dj)
        end
        if string.sub(aS, dj, dj + 1) == '/*' then
            return i.decode(aS, d5(aS, dj))
        end
        return d6(aS, dj)
    end
    function i.null()
        return i.null
    end
    function d4(aS, dj)
        local dl = {}
        local dm = string.len(aS)
        assert(
            string.sub(aS, dj, dj) == '[',
            'decode_scanArray called but array does not start at position ' .. dj .. ' in string:\n' .. aS
        )
        dj = dj + 1
        local dn = 1
        repeat
            dj = da(aS, dj)
            assert(dj <= dm, 'JSON String ended unexpectedly scanning array.')
            local dk = string.sub(aS, dj, dj)
            if dk == ']' then
                return dl, dj + 1
            end
            if dk == ',' then
                dj = da(aS, dj + 1)
            end
            assert(dj <= dm, 'JSON String ended unexpectedly scanning array.')
            local dp
            dp, dj = i.decode(aS, dj)
            dl[dn] = dp
            dn = dn + 1
        until false
    end
    function d5(aS, dj)
        assert(
            string.sub(aS, dj, dj + 1) == '/*',
            'decode_scanComment called but comment does not start at position ' .. dj
        )
        local dq = string.find(aS, '*/', dj + 2)
        assert(dq ~= nil, 'Unterminated comment in string at ' .. dj)
        return dq + 2
    end
    function d6(aS, dj)
        local dr = {['true'] = true, ['false'] = false, ['null'] = nil}
        local ds = {'true', 'false', 'null'}
        for ct, ag in pairs(ds) do
            if string.sub(aS, dj, dj + string.len(ag) - 1) == ag then
                return dr[ag], dj + string.len(ag)
            end
        end
        assert(nil, 'Failed to scan constant from string ' .. aS .. ' at starting position ' .. dj)
    end
    function d7(aS, dj)
        local dq = dj + 1
        local dm = string.len(aS)
        local dt = '+-0123456789.e'
        while string.find(dt, string.sub(aS, dq, dq), 1, true) and dq <= dm do
            dq = dq + 1
        end
        local du = string.sub(aS, dj, dq - 1)
        return du, dq
    end
    function d8(aS, dj)
        local dp = {}
        local dm = string.len(aS)
        local aA, c_
        assert(
            string.sub(aS, dj, dj) == '{',
            'decode_scanObject called but object does not start at position ' .. dj .. ' in string:\n' .. aS
        )
        dj = dj + 1
        repeat
            dj = da(aS, dj)
            assert(dj <= dm, 'JSON string ended unexpectedly while scanning object.')
            local dk = string.sub(aS, dj, dj)
            if dk == '}' then
                return dp, dj + 1
            end
            if dk == ',' then
                dj = da(aS, dj + 1)
            end
            assert(dj <= dm, 'JSON string ended unexpectedly scanning object.')
            aA, dj = i.decode(aS, dj)
            assert(dj <= dm, 'JSON string ended unexpectedly searching for value of key ' .. aA)
            dj = da(aS, dj)
            assert(dj <= dm, 'JSON string ended unexpectedly searching for value of key ' .. aA)
            assert(string.sub(aS, dj, dj) == ':', 'JSON object key-value assignment mal-formed at ' .. dj)
            dj = da(aS, dj + 1)
            assert(dj <= dm, 'JSON string ended unexpectedly searching for value of key ' .. aA)
            c_, dj = i.decode(aS, dj)
            dp[aA] = c_
        until false
    end
    local dv = {['\\t'] = '\t', ['\\f'] = '\f', ['\\r'] = '\r', ['\\n'] = '\n', ['\\b'] = '\b'}
    setmetatable(
        dv,
        {__index = function(aT, ag)
                return string.sub(ag, 2)
            end}
    )
    function d9(aS, dj)
        assert(dj, 'decode_scanString(..) called without start position')
        local dw = string.sub(aS, dj, dj)
        assert(dw == [["]] or dw == [[']], 'decode_scanString called for a non-string')
        local aT = {}
        local ct, di = dj, dj
        while string.find(aS, dw, di + 1) ~= di + 1 do
            local dx = di
            ct, di = string.find(aS, '\\.', di + 1)
            local dy, dz = string.find(aS, dw, dx + 1)
            if not ct or dy < ct then
                ct, di = dy, dz - 1
            end
            table.insert(aT, string.sub(aS, dx + 1, ct - 1))
            if string.sub(aS, ct, di) == '\\u' then
                local dA = string.sub(aS, di + 1, di + 4)
                di = di + 4
                local cF = tonumber(dA, 16)
                assert(cF, 'String decoding failed: bad Unicode escape ' .. dA .. ' at position ' .. ct .. ' : ' .. di)
                local dy
                if cF < 0x80 then
                    dy = string.char(cF % 0x80)
                elseif cF < 0x800 then
                    dy = string.char(0xC0 + math.floor(cF / 64) % 0x20, 0x80 + cF % 0x40)
                else
                    dy =
                        string.char(
                        0xE0 + math.floor(cF / 4096) % 0x10,
                        0x80 + math.floor(cF / 64) % 0x40,
                        0x80 + cF % 0x40
                    )
                end
                table.insert(aT, dy)
            else
                table.insert(aT, dv[string.sub(aS, ct, di)])
            end
        end
        table.insert(aT, string.sub(di, di + 1))
        assert(
            string.find(aS, dw, di + 1),
            'String decoding failed: missing closing ' ..
                dw .. ' at position ' .. di .. '(for string at position ' .. dj .. ')'
        )
        return table.concat(aT, ''), di + 2
    end
    function da(aS, dj)
        local dB = ' \n\r\t'
        local dm = string.len(aS)
        while string.find(dB, string.sub(aS, dj, dj), 1, true) and dj <= dm do
            dj = dj + 1
        end
        return dj
    end
    local dC = {
        ['"'] = '\\"',
        ['\\'] = '\\\\',
        ['/'] = '\\/',
        ['\b'] = '\\b',
        ['\f'] = '\\f',
        ['\n'] = '\\n',
        ['\r'] = '\\r',
        ['\t'] = '\\t'
    }
    function d3.encodeString(aS)
        local aS = tostring(aS)
        return aS:gsub(
            '.',
            function(dD)
                return dC[dD]
            end
        )
    end
    function dc(aT)
        if aT == i.EMPTY_ARRAY then
            return true, 0
        end
        if aT == i.EMPTY_OBJECT then
            return false
        end
        local dE = 0
        for ag, ah in pairs(aT) do
            if type(ag) == 'number' and math.floor(ag) == ag and 1 <= ag then
                if not dd(ah) then
                    return false
                end
                dE = math.max(dE, ag)
            else
                if ag == 'n' then
                    if ah ~= (aT.n or #aT) then
                        return false
                    end
                else
                    if dd(ah) then
                        return false
                    end
                end
            end
        end
        return true, dE
    end
    function dd(cX)
        local aT = type(cX)
        return aT == 'string' or aT == 'boolean' or aT == 'number' or aT == 'nil' or aT == 'table' or
            aT == 'function' and cX == i.null
    end
    return i
end
local dF = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
function h.base64encode(dG)
    return (dG:gsub(
        '.',
        function(dy)
            local dH, dI = '', dy:byte()
            for ct = 8, 1, -1 do
                dH = dH .. (dI % 2 ^ ct - dI % 2 ^ (ct - 1) > 0 and '1' or '0')
            end
            return dH
        end
    ) .. '0000'):gsub(
        '%d%d%d?%d?%d?%d?',
        function(dy)
            if #dy < 6 then
                return ''
            end
            local dD = 0
            for ct = 1, 6 do
                dD = dD + (dy:sub(ct, ct) == '1' and 2 ^ (6 - ct) or 0)
            end
            return dF:sub(dD + 1, dD + 1)
        end
    ) .. ({'', '==', '='})[#dG % 3 + 1]
end
function h.base64decode(dG)
    dG = string.gsub(dG, '[^' .. dF .. '=]', '')
    return dG:gsub(
        '.',
        function(dy)
            if dy == '=' then
                return ''
            end
            local dH, aC = '', dF:find(dy) - 1
            for ct = 6, 1, -1 do
                dH = dH .. (aC % 2 ^ ct - aC % 2 ^ (ct - 1) > 0 and '1' or '0')
            end
            return dH
        end
    ):gsub(
        '%d%d%d?%d?%d?%d?%d?%d?',
        function(dy)
            if #dy ~= 8 then
                return ''
            end
            local dD = 0
            for ct = 1, 8 do
                dD = dD + (dy:sub(ct, ct) == '1' and 2 ^ (8 - ct) or 0)
            end
            return string.char(dD)
        end
    )
end
i = h.createJson()
g.printToConsole('load LuaPanda success', 1)
return g
